package com.atguigu.gulimall.order.config;

import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.lang.Nullable;

import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.Map;

@Configuration
public class MyRabbitConfig {

    @Autowired
    RabbitTemplate rabbitTemplate;
    /**
     * 使用序列话机制进行消息转换
     */
    @Bean
    public MessageConverter messageConverter(){
        return new Jackson2JsonMessageConverter();
    }

    /**
     * 生产者发送消息丢失回调
     */
    @PostConstruct//MyRabbitConfig对象创建完成以后执行这个方法
    public void initRabbitTemplate(){
        rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
            /**
             *
             * @param correlationData
             * @param b 消息是否成功收到
             * @param s 失败的原因
             */
            @Override
            public void confirm(@Nullable CorrelationData correlationData, boolean b, @Nullable String s) {
                System.out.println("correlationData:"+correlationData+"ack:"+b+"case:"+s);
            }
        });
        /**
         * 如果消息没有投递到指定的队列 触发失败回调
         */
        rabbitTemplate.setReturnCallback(new RabbitTemplate.ReturnCallback() {
            /**
             *
             * @param message 投递失败的消息
             * @param i 回复的状态码
             * @param s 回复的文本内容
             * @param s1 当时这个消息发送给那个交换机
             * @param s2 当时这个消息用那个路由建
             */
            @Override
            public void returnedMessage(Message message, int i, String s, String s1, String s2) {
                System.out.println("message:"+message+"状态码:"+i+"文本内容:"+s+"交换机名称:"+s1+"路由建："+s2);
            }
        });
    }

    /**
     * 创建交换机
     * topic:订阅 一对多 根据路由键发送消息 #匹配0个或多个单此 *匹配一个单词
     * direct:直接 一对一
     * fanout：扇出 一对多 都能收到消息
     */
    @Bean
    public Exchange OrderEventExChange(){
        return new TopicExchange("order-event-exchange",true,false);
    }

    /**
     * 创建接受延迟队列
     */
    @Bean
    public Queue OrderReleaseStockQueue(){
        //String name, boolean durable, boolean exclusive, boolean autoDelete, Map<String, Object> arguments
        return new Queue("order-release-stock",true,false,false);
    }

    /**
     * 延迟队列
     * @return
     */
    @Bean
    public Queue OrderDelayQueue(){
        //String name, boolean durable, boolean exclusive, boolean autoDelete, Map<String, Object> arguments
        Map<String,Object> map = new HashMap<>();
        map.put("x-dead-letter-exchange","order-event-exchange");
        map.put("x-dead-letter-routing-key","order.release");
        map.put("x-message-ttl",120000);
        return new Queue("order-delay-stock",true,false,false,map);
    }
    /**
     * 死信队列邦定交换机
     */
    @Bean
    public Binding OrderLockedBinding(){
        return new Binding("order-delay-stock",
                                 Binding.DestinationType.QUEUE,
                                 "order-event-exchange",
                                 "order.locked",null);
    }

    /**
     * 普通队列邦定交换机
     */
    @Bean
    public Binding OrderReleaseBinding(){
        return new Binding("order-release-stock",
                                 Binding.DestinationType.QUEUE,
                                 "order-event-exchange",
                                 "order.release.#",null);
    }

    /**
     * 订单和库存绑定
     */
    @Bean
    public Binding OrderReleaseWareBinding(){
        return new Binding("stock-release-stock",
                Binding.DestinationType.QUEUE,
                "order-event-exchange",
                "order.release.stock.#",null);
    }
}
